﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace PathFinder
{
    public class PropertiesManager
    {
        #region class definitions
       
        static Pen pen = new Pen(new SolidBrush(Color.Black), 4);
        static Brush black = new SolidBrush(Color.Black);
        static Brush white = new SolidBrush(Color.White);
        static Font font = new Font("Arial", 8);
        GraphLine CurrentLine;
        TextBox NameTextBox;
        public PictureBox SlopePreviewPictureBox;
        ComboBox SlopeComboBox;
        ComboBox DirectionPowerComboBox;
        ComboBox FeasibilityComboBox;
        CheckBox IsRequiredCheckBox;
        TextBox LengthTextBox;
        Graphics graphics;
        Button SavePropertiesButton;
        Button CancelPropertiesButton;
        public bool massEdit = false;
        Bitmap tempBitmap;
        public PropertiesManager(TextBox nameTextBox, PictureBox slopePreviewPictureBox, ComboBox slopeComboBox, ComboBox directionPowerComboBox, 
         ComboBox feasibilityComboBox, CheckBox isRequiredCheckBox,TextBox lengthTextBox, Button savePropertiesButton, Button cancelPropertiesButton)
        {
            NameTextBox = nameTextBox;
            SlopeComboBox = slopeComboBox;
            SlopePreviewPictureBox = slopePreviewPictureBox;
            SlopePreviewPictureBox.CreateGraphics();
            DirectionPowerComboBox = directionPowerComboBox;
            FeasibilityComboBox = feasibilityComboBox;
            IsRequiredCheckBox = isRequiredCheckBox;
            LengthTextBox = lengthTextBox;
            SavePropertiesButton = savePropertiesButton;
            CancelPropertiesButton = cancelPropertiesButton;
            SlopeComboBox.TextChanged += new System.EventHandler(this.SlopeComboBoxTextChanged);
            SlopeComboBox.SelectedIndex = 0;
            SavePropertiesButton.Click += new System.EventHandler(this.Save);
            CancelPropertiesButton.Click += new System.EventHandler(this.Cancel);
            graphics = SlopePreviewPictureBox.CreateGraphics();
        }
        
        #endregion


        public  void Load(GraphLine dummy)
        {
            if (dummy == null) return;
            CurrentLine = dummy;
            NameTextBox.Text = CurrentLine.properties.Name;
            SlopeComboBox.SelectedIndex = (int)CurrentLine.properties.Direction;
            DirectionPowerComboBox.SelectedIndex = CurrentLine.properties.DirectionIndex;
            FeasibilityComboBox.SelectedIndex = (int)CurrentLine.properties.Quality;
            IsRequiredCheckBox.Checked = CurrentLine.properties.IsRequired;
            LengthTextBox.Text = ((int)dummy.Length()).ToString() + " pts";
            DrawSlopePreview();
        }

        private void Save(object sender, EventArgs e)
        {
            CurrentLine.properties.update(NameTextBox.Text, (LineProperties.Directions) SlopeComboBox.SelectedIndex, DirectionPowerComboBox.SelectedIndex,
                IsRequiredCheckBox.Checked,
                (LineProperties.Qualities) Enum.ToObject(typeof(LineProperties.Qualities),FeasibilityComboBox.SelectedIndex));
            if (massEdit)
            {
                MainForm.instance.LoadNextLine();
            }
            else
            {
                MainForm.instance.PropertiesGroupBox.Visible = false;
            }
        }

        private void Cancel(object sender, EventArgs e)
        {
            MainForm.instance.PropertiesGroupBox.Visible = false;
        }

        private void SlopeComboBoxTextChanged(object sender, EventArgs e)
        {
            if (SlopeComboBox.SelectedIndex == 0)
            {
                DirectionPowerComboBox.Enabled = false;
            }
            else
            {
                DirectionPowerComboBox.Enabled = true;
            }
        }

        private void DrawSlopePreview()
        {
            graphics.Clear(Color.White);
            graphics.Dispose();
            graphics = SlopePreviewPictureBox.CreateGraphics();
            Point a = new Point();
            Point b = new Point();
            GetPoints(ref a, ref b);
            graphics.DrawLine(pen, a, b);
            //BOD A
            graphics.FillEllipse(black, a.X - 7, a.Y - 7, 14, 14);
            graphics.FillEllipse(white, a.X - 6, a.Y - 6, 12, 12);
            graphics.DrawString("A", font, black, a.X - 5, a.Y - 6);

            //BOD B

            graphics.FillEllipse(black, b.X - 7, b.Y - 7, 14, 14);
            graphics.FillEllipse(white, b.X - 6, b.Y - 6, 12, 12);
            graphics.DrawString("B", font, black, b.X - 5, b.Y - 6);

            tempBitmap = new Bitmap(SlopePreviewPictureBox.Size.Width, SlopePreviewPictureBox.Size.Height);
            SlopePreviewPictureBox.DrawToBitmap(tempBitmap, new Rectangle(0, 0, SlopePreviewPictureBox.Width, SlopePreviewPictureBox.Height));
        }

        private void GetPoints(ref Point aPoint, ref Point bPoint)
        {
            //kruznice v boxu 60x60: (x - 30)^2 +(y - 30)^2 = r^2
            Point vector = new Point(CurrentLine.a.point.X - CurrentLine.b.point.X, CurrentLine.a.point.Y - CurrentLine.b.point.Y);
            double a = -vector.Y;
            double b = vector.X;
            double c = -(a * 30 + b * 30);
            double x1, x2, y1, y2;
            int r = 20;

            if (b!= 0)
            {
                //A * Y^2 + B * Y + C = 0

                double kvadrA = b * b + a * a;
                double kvadrB = 2 * a * c + 60 * a * b - 60 * b * b;
                double kvadrC = c * c + 60 * b * c + 1800 * b * b - r * r * b * b;
                double determinant = kvadrB * kvadrB - 4 * kvadrA * kvadrC;

                x1 = ((-kvadrB + Math.Pow(determinant, 0.5)) / (2 * kvadrA));
                x2 = ((-kvadrB - Math.Pow(determinant, 0.5)) / (2 * kvadrA));
                y1 = (a * x1 + c) / (-b);
                y2 = (a * x2 + c) / (-b);
                
            }
            else
            {
                double kvadrA = b * b + a * a;
                double kvadrB = 2 * b * c + 60 * a * b - 60 * a * a;
                double kvadrC = c * c + 60 * a * c + 1800 * a * a - r * r * a * a;
                double determinant = kvadrB * kvadrB - 4 * kvadrA * kvadrC;
                y1 = ((-kvadrB + Math.Pow(determinant, 0.5)) / (2 * kvadrA));
                y2 = ((-kvadrB - Math.Pow(determinant, 0.5)) / (2 * kvadrA));
                x1 = (b * y1 + c) / (-a);
                x2 = (b * y2 + c) / (-a);
            }
            
            //nyni priradit ke spravnym bodum PODLE vzdalenosti od pocatku
            if (CurrentLine.a.point.X != CurrentLine.b.point.X)
            {
                if (CurrentLine.a.point.X < CurrentLine.b.point.X)
                {
                    if (x1 < x2)
                    {
                        aPoint.X = (int)x1;
                        aPoint.Y = (int)y1;
                        bPoint.X = (int)x2;
                        bPoint.Y = (int)y2;
                    }
                    else
                    {
                        bPoint.X = (int)x1;
                        bPoint.Y = (int)y1;
                        aPoint.X = (int)x2;
                        aPoint.Y = (int)y2;
                    }
                }
                else
                {
                    if (x1 > x2)
                    {
                        aPoint.X = (int)x1;
                        aPoint.Y = (int)y1;
                        bPoint.X = (int)x2;
                        bPoint.Y = (int)y2;
                    }
                    else
                    {
                        bPoint.X = (int)x1;
                        bPoint.Y = (int)y1;
                        aPoint.X = (int)x2;
                        aPoint.Y = (int)y2;
                    }
                }
            }
            else
            {
                if (CurrentLine.a.point.Y < CurrentLine.b.point.Y)
                {
                    if (y1 < y2)
                    {
                        aPoint.X = (int)x1;
                        aPoint.Y = (int)y1;
                        bPoint.X = (int)x2;
                        bPoint.Y = (int)y2;
                    }
                    else
                    {
                        bPoint.X = (int)x1;
                        bPoint.Y = (int)y1;
                        aPoint.X = (int)x2;
                        aPoint.Y = (int)y2;
                    }
                }
                else
                {
                    if (y1 > y2)
                    {
                        aPoint.X = (int)x1;
                        aPoint.Y = (int)y1;
                        bPoint.X = (int)x2;
                        bPoint.Y = (int)y2;
                    }
                    else
                    {
                        bPoint.X = (int)x1;
                        bPoint.Y = (int)y1;
                        aPoint.X = (int)x2;
                        aPoint.Y = (int)y2;
                    }
                }
            }
            aPoint.X -= 2;
            aPoint.Y -= 2;
            bPoint.X -= 2;
            bPoint.Y -= 2;
        }

    }
}
